#ifndef __EPOLL_SERVER_HPP__
#define __EPOLL_SERVER_HPP__

#include <iostream>

#include <cerrno>
#include <cstring>

#include <unistd.h>

#include "Sock.hpp"
#include "log.hpp"
#include "Epoll.hpp"

static const uint16_t default_port = 8080;
static const int gnum = 64;

namespace dsh_epoll
{
    class EpollServer
    {
    public:
        EpollServer(const uint16_t& port = default_port)
            : _port(port)
            , _revs_num(gnum)
        {
            // 申请struct epoll_event的空间
            _revs = new struct epoll_event[_revs_num];

            // 创建socket
            _listensock = Sock::Socket();
            Sock::Bind(_listensock, _port);
            Sock::Listen(_listensock);

            // 创建epoll模型
            _epfd = Epoll::CreateEpoll();
            logMessage(DEBUG, "init success, listensock: %d, epfd: %d", _listensock, _epfd);
        
            // 将listensock设置进epoll用来获取已建立好连接的sock
            if (!Epoll::CtlEpoll(_epfd, EPOLL_CTL_ADD, _listensock, EPOLLIN)) exit(6);

            logMessage(DEBUG, "add listensock to epoll success");
        }
        ~EpollServer()
        {
            if (_listensock > 0) close(_listensock);
            if (_epfd > 0) close(_epfd);
            if (_revs) delete[] _revs;
        }

        void Start()
        {
            while (true)
            {
                int n = Epoll::WaitEpoll(_epfd, _revs, _revs_num, 5000);

                switch(n)
                {
                case 0:
                    logMessage(DEBUG, "timeout...");
                    break;
                case -1:
                    logMessage(WARNING, "epoll wait error: %s", strerror(errno));
                    break;
                default:
                    HandlerEvent(n);
                    break;
                }
            }
        }
        private:
        void Accepter()
        {
            std::string clientip;
            uint16_t clientport;
            int sock = Sock::Accept(_listensock, &clientip, &clientport);
            if (sock < 0)
            {
                logMessage(WARNING, "accept error!");
                return;
            }

            // 将连接号的sock添加到epoll中
            if (!Epoll::CtlEpoll(_epfd, EPOLL_CTL_ADD, sock, EPOLLIN)) return;

            logMessage(DEBUG, "add new sock: %d to epoll success", sock);
        }

        void Recver(int fd)
        {
            char buffer[10240];
            ssize_t n = recv(fd, buffer, sizeof(buffer) - 1, 0);
            if (n > 0)
            {
                // 假设读到了完整的数据
                buffer[n] = 0;
                logMessage(DEBUG, "client[%d]: %s", fd, buffer);
            }
            else if (n == 0)
            {
                // 对端关闭
                logMessage(NORMAL, "client %d quit, me too...", fd);
                // 一定是先从epoll中删除该fd
                bool res = Epoll::CtlEpoll(_epfd, EPOLL_CTL_DEL, fd, 0); // 删除event设置为0即可
                // 再关闭文件描述符
                close(fd);
            }
            else
            {
                logMessage(NORMAL, "recv errro: %s", strerror(errno));
                bool res = Epoll::CtlEpoll(_epfd, EPOLL_CTL_DEL, fd, 0);
                close(fd);
            }
        }

        void HandlerEvent(int n)
        {
            for (int i = 0; i < n; i++)
            {
                uint32_t revents = _revs[i].events;
                int fd = _revs[i].data.fd;
                
                // 读事件就绪
                if (revents & EPOLLIN)
                {
                    // listensock就绪
                    if (fd == _listensock) Accepter();
                    // 其他sock就绪
                    else Recver(fd);
                }
            }
        }
    private:
        int _listensock;
        uint16_t _port;
        int _epfd;
        struct epoll_event* _revs;
        int _revs_num;
    };
}

#endif